package tech.yqyl.git;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.text.StrFormatter;
import com.google.common.base.Splitter;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import tech.yqyl.StringUtil;
import tech.yqyl.YamlUtils;
import tech.yqyl.config.GitConfig;
import tech.yqyl.solo.BlogInfo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @className: GitRepository
 * @description:
 * @author: caoyangjie
 * @date: 2024/9/6
 **/
public class GitRepository {
    private static GitRepository repos;
    Git git = null;
    private GitRepository(String repository, String localDir, String imgDir, String username, String token){
        this.repository = repository;
        this.baseDir = localDir;
        this.username = username;
        this.token = token;
        this.imgDir = imgDir;
        try {
            git = Git.open(new File(baseDir));
        } catch (IOException e) {
        }
    }
    private String repository;
    private String baseDir;
    private String imgDir;
    private String username;
    private String token;

    public static GitRepository init() {
        synchronized (GitRepository.class) {
            if( repos==null ) {
                GitConfig gitConfig = YamlUtils.getConfig().getGit();
                repos = new GitRepository(gitConfig.getRepoUrl(), gitConfig.getLocalDir(), gitConfig.getImgDir(), gitConfig.getUsername(), gitConfig.getToken());
            }
        }
        return repos;
    }

    public boolean cloneRepository() {
        try {
            Git git = Git.cloneRepository()
                    .setURI(this.repository)
                    .setDirectory(new File(baseDir))
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, token))
                    .call();
        } catch (GitAPIException e) {
            System.err.println(StrFormatter.format("git clone {} err: {}", repository, e.getMessage()));
            return false;
        }
        return true;
    }

    public boolean commit(String tag, String commitInfo) {
        try {
            // 添加更改
            git.add().addFilepattern(imgDir.concat(File.separator).concat(StringUtil.hashString(tag))).call();
            // 提交更改
            git.commit().setMessage(StringUtil.isEmpty(commitInfo)?"提交部分图片":commitInfo).call();
        } catch (Exception e) {
            System.err.println(StrFormatter.format("文件提交失败!err=>{}", e.getMessage()));
            return false;
        }
        return true;
    }

    public void store(String tag, Set<String> imageUrls, BlogInfo... blog) {
        imageUrls.parallelStream().forEach(image->{
            String fileName = StringUtil.hashString(image).concat(".").concat(getImageType(image));
            if( image.startsWith("http://") || image.startsWith("https") ) {
                try {
                    downloadImage(image, tag, fileName);
                } catch (Exception e) {
                    System.err.println(StrFormatter.format("下载图片失败!err=>{}", e.getMessage()));
                }
            } else {
                try{
                    String githubUri = YamlUtils.getConfig().getImgBed().getGithubUri();
                    if( !StringUtil.isEmpty(githubUri) ) {
//                        downloadImage();
                        downloadGithubImg( image, tag, fileName, blog );
                    }
                    copyImage(image, tag, fileName, blog);
                } catch(Exception e){
                    if( e instanceof FileAlreadyExistsException) {
                    } else {
                        System.err.println(StrFormatter.format("移动图片[{}]失败!err=>{}", image, e.getMessage()));
                    }
                }
            }
        });
    }

    private void copyImage(String image, String tag, String fileName, BlogInfo... blogs) {
        if( blogs==null || blogs.length==0 ) {
            throw new RuntimeException(StrFormatter.format("拷贝文件 {} 到 目标目录失败,未给定拷贝源文件的绝对路径!", image ));
        }
        BlogInfo blog = blogs[0];
        // 创建目录（如果不存在）
        String imageParentPath = baseDir.concat(File.separator).concat(imgDir).concat(File.separator).concat(StringUtil.hashString(tag)).concat(File.separator);
        File directory = new File(imageParentPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        String destImagePath = imageParentPath.concat(fileName);
        String imageSourcePath = "";
        if( image.startsWith("/") ) {// 处理 /home/caoyangjie/images/bacd.png 这种
            imageSourcePath = image;
        } else if( image.startsWith("./") ){ // 处理 ./asset/abcd.png 这种
            imageSourcePath = blog.getBlogFile().getParentFile().getAbsolutePath().concat(File.separator).concat(image.substring(1));
        } else { // 处理 asset/abcd.png
            imageSourcePath = blog.getBlogFile().getParentFile().getAbsolutePath().concat(File.separator).concat(image);
        }
        File sourceImage = new File(imageSourcePath);
        if( !sourceImage.exists() ) {
            throw new RuntimeException(StrFormatter.format("拷贝文件 {} 到 目标目录失败,给定拷贝源文件的绝对路径不存在源文件!", imageSourcePath ));
        }
        try {
            Files.copy(sourceImage.toPath(), new File(destImagePath).toPath());
        } catch (IOException e) {
            throw new RuntimeException(StrFormatter.format("拷贝文件 {} 到 目标 {} 路径,发生异常，原因为： [{}]!", imageSourcePath, destImagePath, e.getMessage()));
        }
    }

    public void downloadGithubImg(String image, String tag, String fileName, BlogInfo... blogs) throws IOException {
        String imageUrl;
        if( blogs==null || blogs.length==0 ) {
            throw new RuntimeException(StrFormatter.format("拷贝文件 {} 到 目标目录失败,未给定拷贝源文件的绝对路径!", image ));
        }
        String githubUri = YamlUtils.getConfig().getImgBed().getGithubUri();
        if( image.startsWith("./") ) {
            imageUrl = githubUri.concat(image.replace("\\.",""));
        } else if( image.startsWith("/") ) {
            imageUrl = githubUri.concat(githubUri.endsWith("/")?image.substring(1):image);
        } else {
            imageUrl = githubUri.concat(image);
        }
        BlogInfo blog = blogs[0];
        String downFilePathValue = blog.getBlogFile().getParentFile().getAbsolutePath().concat(File.separator).concat(image);
        Path downFilePath = Paths.get(downFilePathValue);
        String realParentPath = downFilePath.getParent().toFile().getAbsolutePath();
        if( !Paths.get(realParentPath.concat(File.separator).concat(fileName)).toFile().exists() ) {
            System.out.println("----------------开始下载图片------------------------");
            downFilePath.getParent().toFile().mkdirs();
        } else {
            System.out.println("----------------图片已经存在------------------------");
            return;
        }
        // 创建 HttpClient 实例
        HttpHost proxy = new HttpHost(YamlUtils.getConfig().getProxy().getIp(), YamlUtils.getConfig().getProxy().getPort());
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000) // 连接超时
                .setSocketTimeout(10000)  // 数据传输超时
                .setConnectionRequestTimeout(10000) // 请求超时
                .build();
        try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setProxy(proxy).build()) {
            System.err.println(StrFormatter.format("开始下载图片：{}", imageUrl));
            HttpGet httpGet = new HttpGet(imageUrl);
            HttpResponse response = httpClient.execute(httpGet);

            // 检查响应状态
            if (response.getStatusLine().getStatusCode() == 200) {
                // 获取响应内容
                try (InputStream inputStream = response.getEntity().getContent();
                     FileOutputStream fileOutputStream = new FileOutputStream(new File(realParentPath, fileName))) {

                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, bytesRead);
                    }
                }
            } else {
                System.err.println("下载失败，HTTP 状态码：" + response.getStatusLine().getStatusCode());
            }
        }
    }

    private void downloadImage(String imageUrl, String tag, String fileName) throws IOException {
        // 创建目录（如果不存在）
        String imageParentPath = baseDir.concat(File.separator).concat(imgDir).concat(File.separator).concat(StringUtil.hashString(tag)).concat(File.separator);
        File directory = new File(imageParentPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        // 创建 HttpClient 实例
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000) // 连接超时
                .setSocketTimeout(10000)  // 数据传输超时
                .setConnectionRequestTimeout(10000) // 请求超时
                .build();
        try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build()) {
            System.err.println(StrFormatter.format("开始下载图片：{}", imageUrl));
            HttpGet httpGet = new HttpGet(imageUrl);
            HttpResponse response = httpClient.execute(httpGet);

            // 检查响应状态
            if (response.getStatusLine().getStatusCode() == 200) {
                // 获取响应内容
                try (InputStream inputStream = response.getEntity().getContent();
                     FileOutputStream fileOutputStream = new FileOutputStream(new File(directory, fileName))) {

                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, bytesRead);
                    }
                }
            } else {
                System.err.println("下载失败，HTTP 状态码：" + response.getStatusLine().getStatusCode());
            }
        }
    }

    public void push() {
        try {
            // 推送代码
            git.push()
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, token)) // 使用令牌替代密码
                    .call();
            System.out.println("已推送到远程仓库！");
        } catch (Exception e) {
            System.err.println(StrFormatter.format("push仓库失败,原因：{}", e.getMessage()));
        }
    }

    public static String getImageType(String imageUrl) {
        if (imageUrl == null || imageUrl.isEmpty()) {
            throw new RuntimeException("图片路径不允许为空!");
        }

        if (imageUrl.contains(".jpg") || imageUrl.contains(".jpeg")) {
            return "JPEG";
        } else if (imageUrl.contains(".png")) {
            return "PNG";
        } else if (imageUrl.contains(".gif")) {
            return "GIF";
        } else if (imageUrl.contains(".bmp")) {
            return "BMP";
        } else if (imageUrl.contains(".svg")) {
            return "SVG";
        } else {
            return "PNG";
        }
    }

    public static void main(String[] args) {
        // 定义要克隆的仓库地址和本地目录
        GitRepository repo = GitRepository.init();
        Set<String> images = new HashSet<>();
        images.add("https://pics0.baidu.com/feed/738b4710b912c8fc2d7c72f25cb1184bd7882147.jpeg@f_auto?token=cf7511076d6819e47fa4826861efeecc");
        repo.store("测试一下", images);
    }
}
